package com.weixiao.controller;

import com.alibaba.fastjson.JSON;
import org.redisson.api.RBloomFilter;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;

@RestController
public class SecKillController {
    //这就是布隆过滤器，并且此时线程安全，所有线程公用此过滤器，存入的数据共享
    @Autowired
    private RBloomFilter<String> rBloomFilter;

    //操作redis
    @Autowired
    private StringRedisTemplate redisTemplate;

    //发消息的成员，spring公司提供的
    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * 接收秒杀请求的接口
     * 0.对
     * 1.一个用户针对同一件商品只能购买一次（使用布隆过滤器）
     * 2.判断库存是否足够（redis）
     * 3.放mq
     * 4.return
     *
     * @param goodsId：商品id
     * @param userId：用户id
     */
    @GetMapping("doSeckill")
    public String doSeckill(Integer goodsId, Integer userId) {
        //使用双主键去重，防止同一用户多次抢购同一商品
        String seckillId = userId + "-" + goodsId;
        //使用bloomFilter做去重
        if (rBloomFilter.contains(seckillId)) {
            return "您已经参与过此商品的抢购，请您抢购其他商品";
        }
        rBloomFilter.add(seckillId);
        //判断redis中库存是否足够，先将此商品减1，再判断是否小于-3，因为要保存一定的误差，保证商品一定全部卖完
        //不能先查出来库存，再进行判断并修改，因为此时可能有多个controller请求，线程之间是不安全的
        Long stock = redisTemplate.opsForValue().decrement("seckill_goodsId:" + goodsId);
        if (stock < -3) {
            return "您来晚啦，商品已经抢完啦！";
        }

        //放入mq，不能保证百分百成功
        HashMap<String, Integer> map = new HashMap<>(4);
        map.put("userId", userId);
        map.put("goodsId", goodsId);
        rabbitTemplate.convertAndSend("exchange", "X", JSON.toJSONString(map));

        //返回信息提醒用户
        return "正在拼命抢购中，请稍后去订单中心查看！";
    }
}
